home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 2
/
Meeting Pearls Vol. II (1995)(GTI - Schatztruhe)[!].iso
/
Pearls
/
dev
/
GUI
/
gengui
/
Lib
/
gui_lnk.c
next >
Wrap
C/C++ Source or Header
|
1994-04-29
|
17KB
|
608 lines
#include <exec/libraries.h>
#include <stdlib.h>
#include <exec/types.h>
#include <proto/gadtools.h>
#include <libraries/gadtools.h>
#include <proto/intuition.h>
#include <intuition/intuition.h>
#include <proto/graphics.h>
#include <graphics/text.h>
#include <string.h>
#include <intuition/gadgetclass.h>
#define GL_VBOX -1
#define GL_HBOX -2
#define CUSTOM_KIND -3
#define MODE_NEW 0
#define MODE_RESIZE 1
#define MODE_REFRESH 2
#define MODE_FREE 3
#define MODE_BACKUP 4
#define MODE_RESTORE 5
#define BOXFLG_CUSTOM 1
#define BOXFLG_STRING 2
#define BOXFLG_INTEGER 4
#define BOXFLG_DISABLED 8
#define BOXFLG_BACKUP 16
#define BOXFLG_INITED (1<<15)
#define BOXFLG_SKIPREFRESH (1<<14)
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
struct GadDim {
int Kind;
USHORT Rx,Ry,Cx,Cy,Px,Py,SRx,SRy,SPx,SPy;
USHORT Flags;
};
struct Box {
struct GadDim Dim;
struct Box **Entry;
};
struct WinInfo {
struct Box *Box;
struct Gadget **Gadgets;
struct Gadget *Prev;
struct Window *Window;
struct Gadget *GList;
int FontX,FontY;
struct TextAttr TextAttr;
APTR Visual;
char Mode,Render;
// USHORT MinX,MinY;
};
struct GadInfo {
struct GadDim Dim;
int XSpace,YSpace,GadNum;
int (*CustomFunc)(struct WinInfo *WInfo,
struct NewGadget *NewGad,
struct GadInfo *GadInfo,
int Left, int Top, int Width, int Height);
struct TextAttr *TextAttr;
char *Text;
int GadgetID;
ULONG Flags,UserData;
int (*HookFunc)(struct IntuiMessage *);
ULONG *Tags;
ULONG *SaveTags;
ULONG Code;
struct Gadget *ThisGad;
};
#define GetString(g) (((struct StringInfo * )g->SpecialInfo)->Buffer)
#define GetNumber(g) (((struct StringInfo * )g->SpecialInfo)->LongInt)
#define GetInfo(g) ((struct GadInfo *)(g->UserData))
#define GetUserData(g) (GetInfo(g)->UserData)
ULONG Modify[]={0,0,GTCB_Checked,GTIN_Number,GTLV_Selected,
GTMX_Active,0,GTCY_Active,GTPA_Color,
GTSC_Top,0,GTSL_Level,GTST_String,0};
ULONG Default[]={0,0,FALSE,0,~0,0,0,0,1,0,0,0,(ULONG)"",0};
static ULONG *MergeTags(ULONG *oldlist,ULONG *newlist)
{
ULONG *p;
if(!oldlist) {
oldlist=malloc(16*sizeof(ULONG));
if(!oldlist) return(NULL);
oldlist[0]=16;
oldlist[1]=TAG_DONE;
}
while(*newlist!=TAG_DONE) {
switch(*newlist) {
case TAG_IGNORE: newlist+=2;
break;
case TAG_MORE: newlist=(ULONG *)newlist[1];
break;
case TAG_SKIP: newlist+=2*newlist[1]+2;
break;
default:
p=oldlist+1;
/* passenden Eintrag in der Taglist suchen, bzw Ende der Liste */
while(*p!=TAG_DONE && *p!=*newlist) p+=2;
if(*p==*newlist) {
p[1]=newlist[1]; // alte Daten ueberschreiben
newlist+=2;
} else {
int n=p-oldlist; // Position im Array;
if(n>=oldlist[0]-1) { // Array vergrößern
ULONG *mem;
mem=realloc(oldlist,oldlist[0]+16*sizeof(ULONG));
if(!mem) return(NULL);
oldlist=mem;
p=oldlist+n;
}
*p++=*newlist++;
*p++=*newlist++;
*p++=TAG_DONE;
}
break;
}
}
return(oldlist);
}
BOOL Gui_SetGadgetAttrsA(struct Gadget *gad,struct Window *win,
struct Requester *req, ULONG *Tag)
{
ULONG *newtags;
struct GadInfo *gi;
gi=GetInfo(gad);
if(!gi->SaveTags) {
gi->SaveTags=MergeTags(NULL,gi->Tags);
if(!gi->SaveTags) return(FALSE);
}
newtags=MergeTags(gi->SaveTags,Tag);
if(!newtags) return(FALSE);
gi->SaveTags=newtags;
GT_SetGadgetAttrsA(gad,win,req,(struct TagItem *)Tag);
return(TRUE);
}
BOOL Gui_SetGadgetAttrs(struct Gadget *gad,struct Window *win,
struct Requester *req, ULONG Tag1,...)
{
return(Gui_SetGadgetAttrsA(gad,win,req,&Tag1));
}
int MakeGTGadget(struct WinInfo *winfo, ///
struct GadInfo *gad,
int left, int top, int width, int height)
{
struct NewGadget ng;
if(winfo->Mode==MODE_REFRESH && gad->Dim.Kind>=0) return(0);
ng.ng_LeftEdge=left + (gad->XSpace>>1);
ng.ng_TopEdge=top + (gad->YSpace>>1);
ng.ng_Width=width - gad->XSpace;
ng.ng_Height=height - gad->YSpace;
ng.ng_GadgetText=gad->Text;
ng.ng_TextAttr=gad->TextAttr ? gad->TextAttr : &winfo->TextAttr;
ng.ng_GadgetID=gad->GadgetID;
ng.ng_Flags=gad->Flags;
ng.ng_VisualInfo=winfo->Visual;
ng.ng_UserData=(void *)gad;
gad->Dim.Flags|=BOXFLG_INITED;
if(gad->Dim.Kind>=0) {
// Falls dies kein erneutes aufsetzen ist: SaveTags neu errechnen
if(!(winfo->Box->Dim.Flags & BOXFLG_BACKUP) && winfo->Mode==MODE_NEW) {
ULONG *tags;
static ULONG modifytag[]={0,0,TAG_DONE};
if(gad->SaveTags) free(gad->SaveTags);
gad->SaveTags=NULL;
if(Modify[gad->Dim.Kind]) {
modifytag[0]=Modify[gad->Dim.Kind];
modifytag[1]=Default[gad->Dim.Kind];
tags=MergeTags(NULL,modifytag);
if(!tags) return(1);
gad->SaveTags=tags;
}
tags=MergeTags(gad->SaveTags,gad->Tags);
if(!tags) return(1);
gad->SaveTags=tags;
}
winfo->Prev=gad->ThisGad=winfo->Gadgets[gad->GadNum]=
CreateGadgetA(gad->Dim.Kind,winfo->Prev,&ng,(struct TagItem *)(gad->SaveTags+1));
if(winfo->Prev==NULL) return(1); else return(0);
} else {
return(gad->CustomFunc(winfo,&ng,gad,left,top,width,height));
}
} ///
static int MakeGuiGadget(struct WinInfo *winfo, ///
struct Box *box,
int left,int top,int width,int height)
{
struct Box **p;
int relx=0,rely=0,absx=0,absy=0;
int w,h;
if(box->Dim.Kind>0 || box->Dim.Kind==CUSTOM_KIND)
return(MakeGTGadget(winfo,(struct GadInfo *)box,
left,top,width,height));
if(!box->Entry) return(0);
relx=box->Dim.SRx;
rely=box->Dim.SRy;
absx=box->Dim.SPx;
absy=box->Dim.SPy;
if(!winfo->Render) {
for(p=box->Entry;*p;p++) {
if(MakeGuiGadget(winfo,(*p),0,0,0,0)) return(1);
}
} else {
if(box->Dim.Kind==GL_HBOX) {
width-=absx;
if(width<0) width=0;
for(w=0,p=box->Entry;*p;p++) {
w=width * ((*p)->Dim.Rx)/relx + (*p)->Dim.Px;
h=height * ((*p)->Dim.Ry)/rely + (*p)->Dim.Py;
if(MakeGuiGadget(winfo,(*p),left,top,w,h)) return(1);
left+=w;
}
} else {
height-=absy;
if(height<0) height=0;
for(w=0,p=box->Entry;*p;p++) {
w=width * ((*p)->Dim.Rx)/relx + (*p)->Dim.Px;
h=height * ((*p)->Dim.Ry)/rely + (*p)->Dim.Py;
if(MakeGuiGadget(winfo,(*p),left,top,w,h)) return(1);
top+=h;
}
}
}
return(0);
} ///
static void InitGui(struct WinInfo *winfo,struct Box *box) ///
{
struct Box **p;
int relx=0,rely=0,absx=0,absy=0;
box->Dim.Px+=box->Dim.Cx*winfo->FontX;
box->Dim.Py+=box->Dim.Cy*winfo->FontY;
box->Dim.Cx=0;
box->Dim.Cy=0;
if(!box->Entry || box->Dim.Kind>0 || box->Dim.Kind==CUSTOM_KIND) {
return;
}
for(p=box->Entry;*p;p++) InitGui(winfo,*p);
if(box->Dim.Kind==GL_HBOX) {
for(p=box->Entry;*p;p++) {
relx+=(*p)->Dim.Rx;
absx+=(*p)->Dim.Px;
rely=max(rely,(*p)->Dim.Ry);
absy=max(absy,(*p)->Dim.Py);
}
} else {
for(p=box->Entry;*p;p++) {
rely+=(*p)->Dim.Ry;
absy+=(*p)->Dim.Py;
relx=max(relx,(*p)->Dim.Rx);
absx=max(absx,(*p)->Dim.Px);
}
}
if(relx==0) relx=1;
if(rely==0) rely=1;
box->Dim.SRx=relx;
box->Dim.SRy=rely;
box->Dim.SPx=absx;
box->Dim.SPy=absy;
box->Dim.Flags=BOXFLG_INITED;
for(p=box->Entry;*p;p++) {
box->Dim.Flags|=(*p)->Dim.Flags;
}
return;
} ///
static int BackupGui(struct WinInfo *winfo,struct Box *box) ///
{
struct GadInfo *gad=(struct GadInfo *)box;
int err=0;
if(box->Dim.Flags & (BOXFLG_STRING | BOXFLG_INTEGER)) {
if(box->Dim.Kind==INTEGER_KIND) {
ULONG tags[]={GTIN_Number,0,TAG_DONE};
tags[1]=GetNumber(gad->ThisGad);
MergeTags(gad->SaveTags,tags);
// gad->Code=GetNumber(gad->ThisGad);
} else if(box->Dim.Kind==STRING_KIND) {
ULONG tags[]={GTST_String,0,TAG_DONE};
if(gad->Code) free((void *)gad->Code);
gad->Code=(ULONG)strdup(GetString(gad->ThisGad));
if(!gad->Code) return(1);
tags[1]=gad->Code;
MergeTags(gad->SaveTags,tags); // This is always successful, since
// there is always a GTST_String tag
// in the taglist (see MakeGTGadget)
} else if(box->Dim.Kind==GL_VBOX || box->Dim.Kind==GL_HBOX) {
struct Box **p;
if(!box->Entry) return(0);
for(p=box->Entry; *p; p++) {
err|=BackupGui(winfo,*p);
}
}
}
return(err);
} ///
static void FindCustom(struct WinInfo *winfo,struct Box *box) ///
{
struct GadInfo *gad=(struct GadInfo *)box;
static struct NewGadget ng; /* Just to avoid Enforcer Hits */
if( !(box->Dim.Flags & BOXFLG_CUSTOM)) return;
if(box->Dim.Kind==CUSTOM_KIND) {
gad->CustomFunc(winfo,&ng,gad,0,0,0,0);
} else if(box->Dim.Kind==GL_VBOX || box->Dim.Kind==GL_HBOX) {
struct Box **p;
if(box->Dim.Flags & BOXFLG_CUSTOM) {
if(!box->Entry) return;
for(p=box->Entry; *p; p++) {
FindCustom(winfo,*p);
}
}
}
} ///
struct IntuiMessage *Gui_GetIMsg(struct MsgPort *userport,struct IntuiMessage *imsg) ///
{
struct IntuiMessage *msg;
int ignore=0;
struct Gadget *gad;
if(msg=GT_GetIMsg(userport)) {
*imsg=*msg;
GT_ReplyIMsg(msg);
switch(imsg->Class) {
case IDCMP_MOUSEMOVE:
case IDCMP_GADGETUP:
case IDCMP_GADGETDOWN:
gad=(struct Gadget *)imsg->IAddress;
if(gad && gad->GadgetID>=0) {
struct GadInfo *gi;
ULONG tags[]={0,0,TAG_DONE};
gi=GetInfo(gad);
if(Modify[gi->Dim.Kind]) {
tags[0]=Modify[gi->Dim.Kind];
tags[1]=imsg->Code;
MergeTags(gi->SaveTags,tags); //always successful in this case
}
if(GetInfo(gad)->HookFunc) ignore=GetInfo(gad)->HookFunc(imsg);
}
break;
}
if(!ignore) return(imsg);
}
return(NULL);
} ///
void ClearWindow(struct Window *win)
{
RefreshWindowFrame(win);
EraseRect(win->RPort,win->BorderLeft,
win->BorderTop,
win->Width-1-win->BorderRight,
win->Height-1-win->BorderBottom);
}
int RenderGui(struct Window *win, struct WinInfo *winfo) ///
{
winfo->Window=win;
winfo->Mode=MODE_NEW;
winfo->Render=1;
AskFont(win->RPort,&winfo->TextAttr);
winfo->FontX = win->RPort->Font->tf_XSize;
winfo->FontY = win->RPort->Font->tf_YSize;
winfo->Visual=GetVisualInfoA(win->WScreen,NULL);
if(!(winfo->Box->Dim.Flags & BOXFLG_INITED)) {
InitGui(winfo,winfo->Box);
winfo->Box->Dim.Flags|=BOXFLG_INITED;
}
if(!winfo->Visual) goto exit_fail2;
if(!CreateContext(&winfo->GList)) return(1);
winfo->Prev=winfo->GList;
if(MakeGuiGadget(winfo,winfo->Box,win->BorderLeft,win->BorderTop,
win->Width - win->BorderLeft - win->BorderRight,
win->Height - win->BorderTop - win->BorderBottom))
goto exit_fail3;
AddGList(win,winfo->GList,-1,-1,NULL);
RefreshGList(winfo->GList,win,NULL,-1);
GT_RefreshWindow(win,NULL);
if(winfo->Box->Dim.Flags & BOXFLG_BACKUP) {
winfo->Mode=MODE_RESTORE;
FindCustom(winfo,winfo->Box);
winfo->Box->Dim.Flags &= ~BOXFLG_BACKUP;
}
return(0);
exit_fail3:
if(winfo->GList) FreeGadgets(winfo->GList);
FreeVisualInfo(winfo->Visual);
exit_fail2:
return(1);
} ///
int ResizeGui(struct WinInfo *winfo) ///
{
struct Window *win=winfo->Window;
winfo->Box->Dim.Flags|=BOXFLG_SKIPREFRESH;
winfo->Mode=MODE_BACKUP;
winfo->Render=0;
ClearWindow(win);
FindCustom(winfo,winfo->Box); // Backup od customgadgets
BackupGui(winfo,winfo->Box);
winfo->Mode=MODE_RESIZE;
winfo->Render=1;
if(winfo->GList) {
RemoveGList(win,winfo->GList,-1);
FreeGadgets(winfo->GList);
}
winfo->GList=NULL;
ClearWindow(win);
if(!CreateContext(&winfo->GList)) return(1);
winfo->Prev=winfo->GList;
if(MakeGuiGadget(winfo,winfo->Box,win->BorderLeft,win->BorderTop,
win->Width - win->BorderLeft - win->BorderRight,
win->Height - win->BorderTop - win->BorderBottom))
return(2);
AddGList(win,winfo->GList,-1,-1,NULL);
RefreshGList(winfo->GList,win,NULL,-1);
GT_RefreshWindow(win,NULL);
winfo->Mode=MODE_RESTORE;
winfo->Render=0;
FindCustom(winfo,winfo->Box);
return(0);
} ///
int RefreshGui(struct WinInfo *winfo) ///
{
struct Window *win=winfo->Window;
if(winfo->Box->Dim.Flags&BOXFLG_SKIPREFRESH) {
winfo->Box->Dim.Flags&=~BOXFLG_SKIPREFRESH;
return(0);
}
winfo->Render=1;
winfo->Mode=MODE_REFRESH;
if(MakeGuiGadget(winfo,winfo->Box,win->BorderLeft,win->BorderTop,
win->Width - win->BorderLeft - win->BorderRight,
win->Height - win->BorderTop - win->BorderBottom)) return(1);
RefreshGList(winfo->GList,win,NULL,-1);
GT_RefreshWindow(winfo->Window,NULL);
return(0);
} ///
static void FreeStopGui(struct WinInfo *winfo,int backup) ///
{
winfo->Render=0;
if(backup) {
winfo->Mode=MODE_BACKUP;
FindCustom(winfo,winfo->Box);
winfo->Box->Dim.Flags|=BOXFLG_BACKUP;
}
winfo->Mode=MODE_FREE;
FindCustom(winfo,winfo->Box);
if(winfo->GList) {
RemoveGList(winfo->Window,winfo->GList,-1);
FreeGadgets(winfo->GList);
}
FreeVisualInfo(winfo->Visual);
} ///
void FreeGui(struct WinInfo *winfo)
{
FreeStopGui(winfo,0);
}
void StopGui(struct WinInfo *winfo)
{
FreeStopGui(winfo,1);
}
int RenderSubGui(struct WinInfo *winfo, ///
int left,int top,int width, int height)
{
if(!(winfo->Box->Dim.Flags & BOXFLG_INITED)) {
InitGui(winfo,winfo->Box);
winfo->Box->Dim.Flags|=BOXFLG_INITED;
}
if(MakeGuiGadget(winfo,winfo->Box,left,top,width,height)) return(1);
return(0);
} ///
int ResizeSubGui(struct WinInfo *winfo, ///
int left, int top,int width,int height)
{
if(MakeGuiGadget(winfo,winfo->Box,left,top,width,height)) return(1);
return(0);
} ///
int RefreshSubGui(struct WinInfo *winfo,int left,int top,int width,int height) ///
{
winfo->Mode=MODE_REFRESH;
return(MakeGuiGadget(winfo,winfo->Box,left,top,width,height));
} ///
void FreeSubGui(struct WinInfo *winfo) ///
{
winfo->Mode=MODE_FREE;
FindCustom(winfo,winfo->Box);
} ///
int SubGui(struct WinInfo *parent, struct WinInfo *winfo, ///
int left,int top,int width, int height)
{
int ret=0;
memcpy((void *)(((ULONG)winfo)+2*sizeof(void *)),
(void *)(((ULONG)parent)+2*sizeof(void *)),
sizeof(struct WinInfo)-2*sizeof(void *));
switch(parent->Mode) {
case MODE_NEW: ret=RenderSubGui(winfo,left,top,width,height);
winfo->Box->Dim.Flags&=~BOXFLG_BACKUP;
break;
case MODE_RESIZE: ret=ResizeSubGui(winfo,left,top,width,height);
winfo->Box->Dim.Flags&=~BOXFLG_BACKUP;
break;
case MODE_REFRESH: ret=RefreshSubGui(winfo,left,top,width,height);
break;
case MODE_FREE: FreeSubGui(winfo);
break;
case MODE_RESTORE:
FindCustom(winfo,winfo->Box);
break;
case MODE_BACKUP: ret=BackupGui(winfo,winfo->Box);
FindCustom(winfo,winfo->Box);
winfo->Box->Dim.Flags|=BOXFLG_BACKUP;
break;
}
parent->Prev=winfo->Prev;
return(ret);
} ///